"""
Rules for running tests with a specific value of the //transitions:enabled flag
"""

def _templated_file_impl(ctx):
    out = ctx.outputs.out
    ctx.actions.expand_template(
        template = ctx.file.template,
        output = out,
        substitutions = dict([s.split("=", 1) for s in ctx.attr.substitutions]),
    )
    return DefaultInfo(
        files = depset([out]),
    )

# Replaces substitutions split on `=` in the template. Substitution is a list
# so that is usable with multiple selects,
templated_file = rule(
    attrs = {
        "template": attr.label(
            mandatory = True,
            allow_single_file = True,
        ),
        "substitutions": attr.string_list(),
        "out": attr.output(),
    },
    implementation = _templated_file_impl,
)

def _enable_transition_impl(settings, attr):
    _ = settings
    return {"@io_bazel_rules_docker//transitions:enable": attr.transitions_enabled}

_enable_transition = transition(
    implementation = _enable_transition_impl,
    inputs = [],
    outputs = [
        "@io_bazel_rules_docker//transitions:enable",
    ],
)

def _transitioned_test(ctx):
    source_info = ctx.attr.actual[DefaultInfo]

    # Bazel wants the executable to be generated by this rule, let's oblige by
    # just copying the actual runner.
    executable = None
    if source_info.files_to_run and source_info.files_to_run.executable:
        executable = ctx.actions.declare_file("{}_{}".format(ctx.file.actual.basename, "on" if ctx.attr.transitions_enabled else "off"))
        ctx.actions.run_shell(
            command = "cp {} {}".format(source_info.files_to_run.executable.path, executable.path),
            inputs = [source_info.files_to_run.executable],
            outputs = [executable],
        )
    return [DefaultInfo(
        files = depset(ctx.files.actual),
        runfiles = source_info.default_runfiles.merge(source_info.data_runfiles),
        executable = executable,
    )]

# Defines a test that runs with a specific value of the
# @io_bazel_rules_docker//transitions:enable flag.
transition_test = rule(
    attrs = {
        "actual": attr.label(
            mandatory = True,
            allow_single_file = True,
        ),
        "transitions_enabled": attr.bool(),
        "_allowlist_function_transition": attr.label(
            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
        ),
    },
    cfg = _enable_transition,
    test = True,
    implementation = _transitioned_test,
)
